#pragma once 
#include<iostream>
#include<pthread.h>
#include<queue>

using namespace std;
#define NUM 5
template<class T>
class ThreadPool 
{
  private:
      int thread_num;
      queue<T> task_queue;
      pthread_mutex_t lock;
      pthread_cond_t cond;
  public:
      ThreadPool(int _num=NUM):thread_num(_num)
        {
          pthread_mutex_init(&lock,nullptr);
          pthread_cond_init(&cond,nullptr);
        }
      void LockQueue()
      {
        pthread_mutex_lock(&lock);
      }

      void UnlockQueue()
      {
        pthread_mutex_unlock(&lock);
      }
      void push(const T& task)
      {
        LockQueue();

        task_queue.push(task);
        UnlockQueue();
        wakeup();

      }

        void pop(T& out)
        {
        out=task_queue.front();
        task_queue.pop();
        }

        bool IsEmptyQueue()
        {
          return task_queue.size()==0?true:false;//注意这里队列没有任务就等待
        }

        void wait()
        {
          pthread_cond_wait(&cond,&lock);
        }
        
        void wakeup()
        {
          
          pthread_cond_signal(&cond);
          
        }

     static void* Routine(void* arg)//静态成员函数不可以访问类中的成员变量和成员函数，类对象可以
      {
          pthread_detach(pthread_self());
          ThreadPool<T>* self =(ThreadPool<T>*)arg;

        while(1)
        {
          self-> LockQueue();
          while(self->IsEmptyQueue())
          {
            //wait
            self->wait();
          }
          //task
          T t;
          self->pop(t);          
          self->UnlockQueue();
          //处理任务
          t.Run();          
        }
      }
      void InitThreadPool()
      {
        pthread_t tid[thread_num];//创建线程
        for(int i=0;i<thread_num;i++)
        {
          pthread_create(&tid[i],nullptr,Routine,this);
        }
      }
     ~ThreadPool()
      {
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
      }
};
